int *path;
int **result;
int pathTop;
int resultTop;
int sum;
int *resultColumnSizes;
int cmp(const void *a, const void *b) {
    return *((int *)a) - *((int *)b);
}


void backtracking(int *candidates, int candidatesSize, int target, int startIndex) {
    if (sum > target) return; // 1# 不需要 "|| pathTop == candidatesSize", 因为遍历到最深处后，会自动回溯。
    if (sum == target) {
        int *temp = (int *)malloc(sizeof(int) * pathTop);
        for(int i = 0; i < pathTop; i++) {
            temp[i] = path[i];
       }
       resultColumnSizes[resultTop] = pathTop;
       result[resultTop++] = temp;
       return;
    }
    
    for(int i = startIndex; i < candidatesSize; i++) {
        if (i > startIndex && candidates[i] == candidates[i - 1]) continue; // 2# 使用startIndex去重，对数组排序后，如果本层遍历时，遇到一个已经访问过的节点，则跳过
        path[pathTop++] = candidates[i];
        sum += path[pathTop - 1];
        backtracking(candidates, candidatesSize, target, i + 1);
        sum -= path[--pathTop];
    }
}

int** combinationSum2(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes) {
    path = (int *)malloc(sizeof(int) * candidatesSize);
    result = (int **)malloc(sizeof(int *) * 10000);
    resultColumnSizes = (int *)malloc(sizeof(int) * 10000);

    pathTop = resultTop = sum = 0;

    qsort(candidates, candidatesSize, sizeof(int), cmp); // 3# 快速排序，固定写法
    backtracking(candidates, candidatesSize, target, 0);

    *returnSize = resultTop;
    *returnColumnSizes = (int *)malloc(sizeof(int) * resultTop);
    for(int i = 0; i < resultTop; i++) {
        (* returnColumnSizes)[i] = resultColumnSizes[i];
    }

    return result;
}